package org.tabletopmachine.board;

import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Vector2f;
import org.tabletopmachine.IDrawable;
import org.tabletopmachine.Main;

public class GameBoard implements IDrawable {
	private Rectangle _boardSize; // Size of the game board in inches
	private float _zoom; // How many pixels are one inch
	private Vector2f _viewPoint;
	private Vector2f _currentMousePosition;
	private int _lastMouseX, _lastMouseY;
	private int _currMouseX;
	private int _currMouseY;
	private Color _boardColor;
	private static GameBoard _board;
	private Ruler _ruler;

	public GameBoard(Rectangle boardSize, float zoom, Vector2f pos) {
		_boardSize = boardSize;
		_zoom = zoom;
		_viewPoint = pos;
		_currentMousePosition = new Vector2f();
		_lastMouseX = _lastMouseY = 0;

		_board = this;

		_boardColor = Color.decode("#4DBD33");

		_ruler = new Ruler(Color.red);
	}

	public static GameBoard getBoard() {
		return _board;
	}

	public void init(GameContainer gc) {

	}

	public void update(GameContainer gc, int delta) {
		Input input = gc.getInput();
		_currMouseX = input.getMouseX();
		_currMouseY = input.getMouseY();
		moveViewPoint(input);

		_currentMousePosition.x = ((float) input.getMouseX()) / _zoom + _viewPoint.x;
		_currentMousePosition.y = ((float) input.getMouseY()) / _zoom + _viewPoint.y;
		// try {
		// if (input.isKeyPressed(Input.KEY_W)) {
		// // for (Unit unit : _units) {
		// // unit.MoveForward(1.0f);
		// // }
		// }
		// if (input.isKeyPressed(Input.KEY_S)) {
		// // for (Unit unit : _units) {
		// // unit.MoveBackward(1.0f);
		// // }
		// }
		// if (input.isKeyPressed(Input.KEY_Q)) {
		// // for (Unit unit : _units) {
		// // unit.RotateAroundLeft(1.0f);
		// // }
		// }
		// if (input.isKeyPressed(Input.KEY_E)) {
		// // for (Unit unit : _units) {
		// // unit.RotateAroundRight(1.0f);
		// // }
		// }
		// if (input.isKeyPressed(Input.KEY_A)) {
		// // for (Unit unit : _units) {
		// // unit.MoveLeft(1.0f);
		// // }
		// }
		// if (input.isKeyPressed(Input.KEY_D)) {
		// // for (Unit unit : _units) {
		// // unit.MoveRight(1.0f);
		// // }
		// }
		// } catch (InvalidActionException e) {
		//
		// }
		_lastMouseX = _currMouseX;
		_lastMouseY = _currMouseY;
		_ruler.update(gc, delta);
	}

	private void moveViewPoint(Input input) {
		Vector2f NewPos = new Vector2f(_viewPoint);
		float NewZoom = _zoom;
		// Move Camera
		if (input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON)) {

			int MouseDeltaX = _currMouseX - _lastMouseX;
			int MouseDeltaY = _currMouseY - _lastMouseY;

			NewPos.x = NewPos.x - MouseDeltaX / _zoom;
			NewPos.y = NewPos.y - MouseDeltaY / _zoom;
		}

		// Change Zoom level
		if (input.isMouseButtonDown(Input.MOUSE_MIDDLE_BUTTON)) {

			int MouseDeltaY = _currMouseY - _lastMouseY;
			NewZoom += MouseDeltaY / 5.0f;

			// Restrict zoom
			if (NewZoom <= 5.0f)
				NewZoom = 5.0f;
			if (NewZoom >= 50.0f)
				NewZoom = 50.0f;

			Vector2f Center = new Vector2f(NewPos.x + Main.getDisplayX() / 2.0f / _zoom, NewPos.y + Main.getDisplayY() / 2.0f / _zoom);

			NewPos.x = Center.x - Main.getDisplayX() / 2.0f / NewZoom;
			NewPos.y = Center.y - Main.getDisplayY() / 2.0f / NewZoom;

		}

		// Restrict camera
		if (NewPos.x < 0)
			NewPos.x = 0;
		if (NewPos.y < 0)
			NewPos.y = 0;
		if (NewPos.x > _boardSize.getWidth() - Main.getDisplayX() / NewZoom)
			NewPos.x = _boardSize.getWidth() - Main.getDisplayX() / NewZoom;
		if (NewPos.y > _boardSize.getHeight() - Main.getDisplayY() / NewZoom)
			NewPos.y = _boardSize.getHeight() - Main.getDisplayY() / NewZoom;
		if (NewPos.x <= 0 && NewPos.y <= 0
				&& ((Main.getDisplayX() / NewZoom) >= _boardSize.getWidth() || (Main.getDisplayY() / NewZoom) >= _boardSize.getHeight())) {
			NewZoom = Main.getDisplayX() / _boardSize.getWidth();
			NewPos = new Vector2f(0.0f, 0.0f);
		}
		_viewPoint = NewPos;
		_zoom = NewZoom;

	}

	public void render(GameContainer gc, Graphics g) {
		Color prevColor = g.getColor();

		// Draw green Game Board
		Vector2f BoardScreenCoords = ConvertPositionToScreenCoordinates(new Vector2f(0.0f, 0.0f));
		g.setColor(_boardColor);
		g.fillRect(BoardScreenCoords.getX(), BoardScreenCoords.getY(), ConvertLengthToPixels(_boardSize.getWidth()),
				ConvertLengthToPixels(_boardSize.getHeight()));
		// Draw 1 inch grid
		g.setColor(Color.gray);
		for (int columns = 1; columns < _boardSize.getWidth(); columns++) {
			if (columns % 10 == 0)
				g.setColor(Color.white);
			g.drawLine(columns * _zoom - _viewPoint.x * _zoom, -_viewPoint.y * _zoom, columns * _zoom - _viewPoint.x * _zoom, _boardSize.getHeight() * _zoom
					- _viewPoint.y * _zoom);
			if (columns % 10 == 0)
				g.setColor(Color.gray);
		}
		for (int rows = 1; rows < _boardSize.getHeight(); rows++) {
			if (rows % 10 == 0)
				g.setColor(Color.white);
			g.drawLine(-_viewPoint.x * _zoom, rows * _zoom - _viewPoint.y * _zoom, _boardSize.getWidth() * _zoom - _viewPoint.x * _zoom, rows * _zoom
					- _viewPoint.y * _zoom);
			if (rows % 10 == 0)
				g.setColor(Color.gray);
		}
		g.setColor(prevColor);

		// Current position
		g.drawString("X: " + String.format("%.4g", _currentMousePosition.x) + ", Y: " + String.format("%.4g", _currentMousePosition.y), 10, 40);

		// for (Unit unit : _units) {
		// unit.render(gc, g);
		// }

		_ruler.render(gc, g);
	}

	public Vector2f ConvertPositionToScreenCoordinates(Vector2f pos) {
		Vector2f ScreenCoords = new Vector2f();
		ScreenCoords.x = (pos.x - _viewPoint.x) * _zoom;
		ScreenCoords.y = (pos.y - _viewPoint.y) * _zoom;

		return ScreenCoords;
	}

	public Vector2f ConvertScreenCoordinatesToPosition(float x, float y) {
		return this.ConvertScreenCoordinatesToPosition(new Vector2f(x, y));
	}

	public Vector2f ConvertScreenCoordinatesToPosition(int x, int y) {
		return this.ConvertScreenCoordinatesToPosition(new Vector2f(x, y));
	}

	public Vector2f ConvertScreenCoordinatesToPosition(Vector2f screenCoords) {
		Vector2f Position = new Vector2f();
		Position.x = screenCoords.x / _zoom + _viewPoint.x;
		Position.y = screenCoords.y / _zoom + _viewPoint.y;

		return Position;
	}

	public int ConvertLengthToPixels(float length) {
		return (int) (length * _zoom);
	}

	public Vector2f ConvertPixelsToInches(Vector2f pixels) {
		return new Vector2f(pixels.x / _zoom, pixels.y / _zoom);
	}

	public Vector2f ConvertInchesToPixels(Vector2f inches) {
		return new Vector2f(inches.x * _zoom, inches.y * _zoom);
	}
}